package org.axed.user.client.util;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import org.axed.user.client.AxedInternalError;

/**
 * The "Tower" is a list of integers that always increase.
 *
 * for example:
 * tower.add(1);
 * tower.add(1);
 * tower.add(2);
 * tower.add(1);
 *
 * will result in:
 * 1 2 4 5 
 */
public class Tower {
	/**
	 * The tower list of increasing values. 
	 * (may be out of date - lazy calculation)
	 */
	IntList tlist = new IntList();

	/**
	 * The value list.
	 * (always has the real data.)
	 */
	IntList vlist = new IntList();

	/**
	 * To which point is the tlist valid?
	 */
	int valid = 0; 
 
	/**
	 * Constructor
	 */
	public Tower() {
		tlist.add(0);
	}

	/**
	 * Adds a value.
	 */
	public void add(int v) {
		vlist.add(v);
	}

	/**
	 * Clears the tower.
	 */
	public void clear() {
		vlist.clear();
		tlist.clear();
		tlist.add(0);
		valid = 0;
	}

	/**
	 * Returns a debug string.
	 */
	public String debug() {
		String s = "V: ";
		for(int i = 0; i < vlist.size(); i++) {
			s+= vlist.get(i) + " ";
		}

		s+= "T: ";
		for(int i = 0; i < size(); i++) {
			s += get(i) + " ";
		}

		return s;
	}

  
	public void delete(int start, int end) {
		vlist.removeRange(start, end);
		if (valid >= start) {
			valid = start;
		}
	}

	public int get(int index) {
		if (valid < index) {
			validize(index);
		}
		if (!GWT.isScript() && index >= size()) {
			throw new AxedInternalError("Tower.get getting out of bounds.");
		}
		return tlist.get(index);
	}

	/**
	 * Inserts a value at index.
	 */
	public void insert(int v, int index) {
		vlist.add(index, v);
		if (valid >= index) {
			valid = index;
		}
	}

	public void remove(int index) {		 
		vlist.remove(index);
		if (valid >= index) {
			valid = index;
		}
	}

	/**
	 * Sets a value v at index.
	 *
	 * @return false, if nothing has changed
	 */
	public boolean set(int index, int v) {
		if (vlist.get(index) == v) {
			// do not need to change a thing if already at v
			return false;
		}

		vlist.set(index, v);
		if (valid >= index) {
			valid = index;
		}
		return true;
	}

	public int size() {
		return vlist.size() + 1;
	}

//privates

	/**
	 * Make the tlist valid until index.
	 */
	private void validize(int vi) {
		for(int i = valid + 1; i <= vi; i++) {
			if (tlist.size() > i) {
				tlist.set(i, tlist.get(i - 1) + vlist.get(i - 1));
			} else {
				tlist.add(tlist.get(i - 1) + vlist.get(i - 1));
			}
		}
		valid = vi;
 	}
}
